﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.IO;

namespace ebookreader
{   
        
    class myComparer : StringComparer
        {
            public override int Compare(string x, string y)
            {
                return String.Compare(x, y, System.Globalization.CultureInfo.CurrentCulture, System.Globalization.CompareOptions.IgnoreCase | System.Globalization.CompareOptions.IgnoreNonSpace);
            }

            public override bool Equals(string x, string y)
            {
                return Compare(x, y) == 0;
            }

            public override int GetHashCode(string obj)
            {
                var sum = 0;
                obj = obj.ToLower();
                for (int i = 0; i < obj.Length; i++)
                {                    
                    var c = obj[i];
                    switch (c)
                    {
                        case 'a':
                        case 'à': sum += (int)'a'; break;
                        case 'e':
                        case 'è':
                        case 'é': sum += (int)'e'; break;
                        case 'i':
                        case 'ì': sum += (int)'i'; break;
                        case 'o':
                        case 'ò': sum += (int)'o'; break;
                        case 'u':
                        case 'ù': sum += (int)'u'; break;
                        default: sum += (int)c; break;
                    }
                    
                }
                return sum;
            }
        }

    public struct filderDes
    {
        public List<string> lang;
        public List<int> eBooks;
    }


    public class el{
        public List<e> l = new List<e>();
    }
    public class e
    {
        public string i;
        //public string t;
        public string t;
        public string a;
        //public string d;
        public string l;
    }


    class Program
    {
        static void Main(string[] args)
        {

            //XmlDocument doc = new XmlDocument();
            //doc.LoadXml(;



            Console.WriteLine("START");
            //createSchema();
            //return;

            XmlSerializer serializer = new XmlSerializer(typeof(RDF));

            if (! File.Exists("../../catalog2.xml"))
            {
                Console.WriteLine("parsing and replacing invalid characters in original catalog");
            var f = File.Open("../../catalog.xml", FileMode.Open, FileAccess.ReadWrite);
            StreamReader r = new StreamReader(f);

            string s = r.ReadToEnd();
            int n = s.Length;
            s = "";
            r.Close();

            GC.Collect();
            f = File.Open("../../catalog.xml", FileMode.Open, FileAccess.ReadWrite);
            r = new StreamReader(f);

            f = File.Open("../../catalog2.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite);
            StreamWriter w = new StreamWriter(f);

            char[] buff = new char[1000000];
            int num=0;
            long sum = 0;
            while ((num = r.ReadBlock(buff, 0, 1000000)) > 0)
            {
                sum += num;
                if (r.EndOfStream)
                {
                    Console.WriteLine(new String(buff).Substring(0, num));
                    w.Write(new String(buff).Substring(0, num).ToString().Replace("&pg", "pg"));
                }
                else
                    w.Write(new String(buff).ToString().Replace("&pg", "pg"));
                Console.Write("\r" + sum/100000.0f + "/\t"+n/100000.0f+"\t"+num+"            ");
            }
            w.Close();
            f.Close();

            Console.WriteLine("succesfully substituted");
            }

            Console.WriteLine("parsing elaborated catalog file...");
            var fs = new FileStream("../../catalog2.xml", FileMode.Open);

            el books = new el();

            string str = "";
            RDF state = null;
            try
            {
                state = serializer.Deserialize(fs) as RDF;
                //var state = serializer.Deserialize(new FileStream("../../catalog.xml", FileMode.Open)) as RDF;
            }
            catch (Exception ex)
            {
                fs.Close();
                File.Delete("../../catalog2.xml");
            }
            Console.WriteLine("loaded...");

            Dictionary<String, filderDes> findList = new Dictionary<string, filderDes>(new myComparer());

            var fi = File.Open("../../cat.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite);
            StreamWriter wr = new StreamWriter(fi);

            int j = 0;
            int num_b = 0;
            foreach (var item in state.etext.Where(e => e.title != null && e.title[0].Text != null && !e.friendlytitle.Value.Equals("")).OrderBy(e => e.friendlytitle.Value))
                {
                    
                if (item.title == null || item.title[0].Text == null )                    
                        continue;
                    num_b++;

                    var ft = item.friendlytitle.Value;
                    var by = (int)ft.LastIndexOf("by");
                    string tit = "", aut = "";
                    if (by == -1)
                    {
                        by = ft.Length;
                        tit = ft;
                    }
                    else
                    {
                        tit = ft.Substring(0, by - 1);
                        aut = ft.Substring(by + 2, ft.Length - by - 2).TrimStart(new char[]{' '});
                    }
                    if (tit.Aggregate(0, (sum, c) => { return sum + ((Convert.ToInt32(c) <= 256) ? 1 : 0); }) < tit.Length * 0.85f)
                        continue;

                    str=item.ID.Replace("etext","")+"<&>";
                    str += tit + "<&>";
                    str += aut + "<&>";
                    str += (item.language != null && item.language.ISO6392 != null) ? item.language.ISO6392.value : "?";
                    wr.WriteLine(str);
                    var lang = (item.language != null && item.language.ISO6392 != null) ? item.language.ISO6392.value : "?";

                    var words = (aut+" "+tit).Split(new char[] { ' ', ',', '-', '(',')','.',',',':',';','-','_','&','"','\'','!','/','[',']' }, StringSplitOptions.RemoveEmptyEntries);
                    
                    for (int i = 0; i < words.Length; i++)
                    {
                        var word = words[i].ToLower();
                        if (findList.ContainsKey(word))
                        {
                            var finddesc = findList[word];
                            if(!finddesc.eBooks.Contains(j))
                                finddesc.eBooks.Add(j);
                            if (!finddesc.lang.Contains(lang))
                                finddesc.lang.Add(lang);
                        }
                        else
                        {
                            findList.Add(word, new filderDes()
                            {
                                eBooks = new List<int>() { j },
                                lang = new List<string>() { lang }
                            });
                        }
                    }




                    j++;
                    //var eb = new e()
                    //{
                    //i=item.ID.Replace("etext",""),
                    //t = tit,
                    ////f=item.friendlytitle.Value,
                    //a = aut,
                    ////d = (item.description != null && item.description.Text != null) ? item.description.Text[0] : "",
                    //l =                
                    //};
                    //books.l.Add(eb);
                    //Console.WriteLine(item.friendlytitle);
                    Console.Write("\r selected books:"+j+"\t of "+num_b+"               ");
                }
            wr.Close();
            fi.Close();
            Console.WriteLine("succesfuly parsed!");


            Console.WriteLine("Building research index...");
            var fin = File.Open("../../finder.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite);
            StreamWriter wr2 = new StreamWriter(fin);
            j = 0;
            foreach (var key in findList.Keys)
            {
                string s = key+"<&>";
                foreach(var eb in findList[key].eBooks)
                    s += eb + ",";                
                s += "<&>";
                foreach (var eb in findList[key].lang)
                    s += eb + ",";
                wr2.WriteLine(s);
                Console.Write("\r processed:" + ++j + "\t of " + findList.Count + "               ");
            }
            wr2.Close();
            fin.Close();
            //XmlSerializer ser = new XmlSerializer(typeof(el));
            //ser.Serialize(wa, books);

            wr2.Close();
            Console.WriteLine("YEAH!!!");
            
            //xmlReader.Read();

            //while (xmlReader.Read())
            //{
            //    xmlReader.MoveToElement();
            //    Console.WriteLine(xmlReader.Name+""+xmlReader.Value);
            //}

        }




        static void createSchema()
        {


            XmlSchemaSet schemaSet = new XmlSchemaSet();
            XmlSchemaInference inference = new XmlSchemaInference();


            for (int i = 0; i < 4; i++)
            {
                XmlTextReader xmlReader = new XmlTextReader("../../"+i+".rdf");
                xmlReader.EntityHandling = EntityHandling.ExpandCharEntities;
                schemaSet = inference.InferSchema(xmlReader);
            }

            Console.WriteLine("Original schema:\n");
            int j = 0;
            foreach (XmlSchema schema in schemaSet.Schemas())
            {
                schema.Write(new FileStream("../../out" + j + ".xsd", FileMode.OpenOrCreate));
                j++;
            }

            Console.WriteLine("FINE:\n");
            //while (true) { }


        }
    }
}
